package com.cheejee.goodscenter.service.impl;

import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

import javax.annotation.Resource;

import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.stereotype.Service;

import com.cheejee.goodscenter.dao.CategoryMapper;
import com.cheejee.goodscenter.dao.GoodsMapper;
import com.cheejee.goodscenter.module.entity.Category;
import com.cheejee.goodscenter.service.CategoryService;
import com.cheejee.goodscenter.service.exception.CheckException;
import com.cheejee.goodscenter.service.exception.DataNotExistException;
import com.cheejee.goodscenter.service.exception.DuplicateException;
import com.cheejee.goodscenter.validated.Check;
import com.cheejee.goodscenter.validated.InsertGroup;
import com.cheejee.goodscenter.validated.UpdateGroup;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;

import cn.hutool.core.collection.CollectionUtil;

/**
 * @author CARRY
 * @Date 2020年10月24日下午6:37:31
 */
@Service
public class CategoryServiceImpl implements CategoryService {

	@Resource
	private CategoryMapper categoryMapper;
	
	@Resource
	private GoodsMapper goodsMapper;

	@Override
	public Page<Category> queryCategory(Integer parentId, String name, Byte level, int pageNum, int pageSize) {

		return PageHelper.startPage(pageNum, pageSize)
				.doSelectPage(() -> categoryMapper.selectBySelective(parentId, name, level));
	}

	@Override
	public Category queryCategoryById(Integer id) {

		return categoryMapper.selectByPrimaryKey(id);
	}

	@Override
	@Check(message = "新增的分类不能为空", group = InsertGroup.class)
	public int addCategory(Category category) {

		changeLevel(category);

		if (!CollectionUtil.isEmpty(categoryMapper.selectBySelective(null, category.getName(), category.getLevel()))) {
			throw new DuplicateException("同级已有同名称分类存在");
		}

		return categoryMapper.insertSelective(category);
	}

	@Override
	@Check(message = "修改的分类不能为空", group = UpdateGroup.class)
	public int changeCategory(Category category) {
		checkExist(category.getId());

		// 检测分类父级是否可用
		if (!checkParent(category)) {
			throw CheckException.builder().checkMessage("分类父级不合法").param("category").build();
		}

		// 设置分类级别
		changeLevel(category);

		// 检测分类名称是否可用
		if (!CollectionUtil.isEmpty(categoryMapper.selectBySelective(null, category.getName(), category.getLevel()))) {
			throw new DuplicateException("同级已有同名称分类存在");
		}

		return categoryMapper.updateByPrimaryKeySelective(category);
	}

	@Override
	public int deleteCategory(Integer... id) {
		for(Integer i : id) {
			if(!CollectionUtil.isEmpty(categoryMapper.selectBySelective(i, null, null))) {
				throw new CheckException("分类下还有子类，不能删除");
			}
			if(!CollectionUtil.isEmpty(goodsMapper.selectBySelective(null, i, null, null, null))) {
				throw new CheckException("分类下还有商品，不能删除");
			}
		}
		
		return categoryMapper.deleteById(id);
	}

	/**
	 * 根据分类父级修改分类级别，在父级的基础上+1
	 *
	 * @param category
	 */
	private void changeLevel(Category category) {
		Integer pid = category.getParentId();
		if (pid == 0) {
			category.setLevel(Byte.valueOf((byte) 1));
			return;
		}

		Category c = categoryMapper.selectByPrimaryKey(pid);
		if (c == null) {
			category.setParentId(0);
			category.setLevel((byte) 1);
		} else {
			category.setLevel((byte) (c.getLevel() + 1));
		}
	}

	/**
	 * 检测分类父级是否可用，可用返回true
	 *
	 * @param category
	 * @return
	 */
	private boolean checkParent(Category category) {
		Integer pid = category.getParentId();
		Integer cid = category.getId();

		if (Objects.equals(pid, cid)) {
			return false;
		}

		if (pid == categoryMapper.selectByPrimaryKey(cid).getParentId()) {
			return true;
		}

		return !checkSon(pid, cid);
	}

	/**
	 * parentId是否是categoryId分类的子类，是则返回true。<br>
	 *
	 * @param parentId
	 * @param categoryId
	 * @return
	 */
	private boolean checkSon(Integer parentId, Integer categoryId) {
		Set<Integer> ids = categoryMapper.selectBySelective(categoryId, null, null).stream().map(Category::getId)
				.collect(Collectors.toSet());

		if(ids.contains(parentId)) {
			return true;
		}
		
		for (Integer id : ids) {
			return checkSon(parentId, id);
		}

		return false;
	}
	
	private void checkExist(Integer id) {
		if(categoryMapper.selectByPrimaryKey(id) == null) {
			throw new DataNotExistException("分类不存在");
		}
	}

}
